package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.piggy.common.core.constant.SecurityConstants;
import com.piggy.common.core.domain.R;
import com.piggy.common.core.exception.GlobalException;
import com.piggy.common.core.exception.base.BaseException;
import com.piggy.common.core.utils.FeignResultUtils;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.utils.sql.SqlUtil;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.logi.sys.bo.LogiCustomerBookQueryBo;
import com.piggy.logi.sys.bo.LogiCustomerExtEditBo;
import com.piggy.logi.sys.bo.LogiCustomerQueryBo;
import com.piggy.logi.sys.domain.LogiCustomer;
import com.piggy.logi.sys.domain.LogiCustomerBook;
import com.piggy.logi.sys.mapper.LogiCustomerMapper;
import com.piggy.logi.sys.service.ILogiCustomerBookService;
import com.piggy.logi.sys.service.ILogiCustomerService;
import com.piggy.logi.sys.vo.LogiCustomerBookVo;
import com.piggy.logi.sys.vo.LogiCustomerExtVo;
import com.piggy.sys.api.RemoteDistrictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 我的客户Service业务层处理
 *
 * @author piggy
 * @date 2023-08-16
 */
@Slf4j
@Service
public class LogiCustomerServiceImpl extends ServiceImpl<LogiCustomerMapper, LogiCustomer> implements ILogiCustomerService {

    @Resource
    private ILogiCustomerBookService bookService;

    @Resource
    private RemoteDistrictService districtService;

    @Override
    public LogiCustomerExtVo queryById(Long customerId) {
        LogiCustomerExtVo vo = getVoById(customerId, LogiCustomerExtVo.class);
        if (ObjectUtil.isEmpty(vo)) {
            return vo;
        }
        return fillData(Lists.newArrayList(vo)).get(0);
    }

    @Override
    public TableDataInfo<LogiCustomerExtVo> queryPageList(LogiCustomerQueryBo bo) {
        PagePlus<LogiCustomer, LogiCustomerExtVo> result = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiCustomerExtVo.class);
        result.setRecordsVo(fillData(result.getRecordsVo()));
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<LogiCustomerExtVo> queryList(LogiCustomerQueryBo bo) {
        List<LogiCustomerExtVo> voList = listVo(buildQueryWrapper(bo), LogiCustomerExtVo.class);
        return fillData(voList);
    }

    public List<LogiCustomerExtVo> fillData(List<LogiCustomerExtVo> extVos) {

        LinkedHashMap<Long, LogiCustomerExtVo> voMap = extVos.stream().collect(LinkedHashMap::new, (m, v) -> m.put(v.getCustomerId(), v), LinkedHashMap::putAll);
        voMap.put(-1L, new LogiCustomerExtVo());
        List<LogiCustomerBookVo> bookExtVos = bookService.queryList(new LogiCustomerBookQueryBo().setCustomerIdList(Lists.newArrayList(voMap.keySet())));

        List<String> cusDistIds = extVos.stream().map(vo-> vo.getCustomerDistrict().toString()).distinct().collect(Collectors.toList());
        cusDistIds.add("-1");

        R<Map<String, String>> cusDistMapR = districtService.getDistrictMap(cusDistIds, SecurityConstants.INNER);
        FeignResultUtils.throwIfFailed(cusDistMapR);

        bookExtVos.stream().peek(Any-> {
            LogiCustomerExtVo extVo = voMap.get(Any.getCustomerId());
            extVo.getBookList().add(Any);
        }).collect(Collectors.toList());

        extVos.stream().peek(Any-> Any.setCustomerDistrictName(ObjectUtil.defaultIfNull(cusDistMapR.getData(), new HashMap<String,String>()).get(Any.getCustomerDistrict().toString()))).collect(Collectors.toList());

        voMap.remove(-1L);
        return Lists.newArrayList(voMap.values());

    }

    private LambdaQueryWrapper<LogiCustomer> buildQueryWrapper(LogiCustomerQueryBo bo) {
        LambdaQueryWrapper<LogiCustomer> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getCustomerId() != null, LogiCustomer::getCustomerId, bo.getCustomerId());
        lqw.like(StrUtil.isNotBlank(bo.getCustomerName()), LogiCustomer::getCustomerName, bo.getCustomerName());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerCode()), LogiCustomer::getCustomerCode, bo.getCustomerCode());
        lqw.eq(StrUtil.isNotBlank(bo.getLeader()), LogiCustomer::getLeader, bo.getLeader());
        lqw.eq(StrUtil.isNotBlank(bo.getPhone()), LogiCustomer::getPhone, bo.getPhone());
        lqw.eq(StrUtil.isNotBlank(bo.getEmail()), LogiCustomer::getEmail, bo.getEmail());
        lqw.eq(StrUtil.isNotBlank(bo.getLegalIdcard()), LogiCustomer::getLegalIdcard, bo.getLegalIdcard());
        lqw.eq(StrUtil.isNotBlank(bo.getLegalIdcardUrl()), LogiCustomer::getLegalIdcardUrl, bo.getLegalIdcardUrl());
        lqw.eq(StrUtil.isNotBlank(bo.getLegalIdcardUrl2()), LogiCustomer::getLegalIdcardUrl2, bo.getLegalIdcardUrl2());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerPost()), LogiCustomer::getCustomerPost, bo.getCustomerPost());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerNature()), LogiCustomer::getCustomerNature, bo.getCustomerNature());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerIndustry()), LogiCustomer::getCustomerIndustry, bo.getCustomerIndustry());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerEntType()), LogiCustomer::getCustomerEntType, bo.getCustomerEntType());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerEntNature()), LogiCustomer::getCustomerEntNature, bo.getCustomerEntNature());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerBizScope()), LogiCustomer::getCustomerBizScope, bo.getCustomerBizScope());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerLogo()), LogiCustomer::getCustomerLogo, bo.getCustomerLogo());
        lqw.eq(bo.getCustomerDate() != null, LogiCustomer::getCustomerDate, bo.getCustomerDate());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerTel()), LogiCustomer::getCustomerTel, bo.getCustomerTel());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerLicense()), LogiCustomer::getCustomerLicense, bo.getCustomerLicense());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerLicenseUrl()), LogiCustomer::getCustomerLicenseUrl, bo.getCustomerLicenseUrl());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerOpenPremit()), LogiCustomer::getCustomerOpenPremit, bo.getCustomerOpenPremit());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerRoadLicense()), LogiCustomer::getCustomerRoadLicense, bo.getCustomerRoadLicense());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerPlateUrl()), LogiCustomer::getCustomerPlateUrl, bo.getCustomerPlateUrl());
        lqw.eq(bo.getCustomerDistrict() != null, LogiCustomer::getCustomerDistrict, bo.getCustomerDistrict());
        lqw.eq(StrUtil.isNotBlank(bo.getCustomerAddress()), LogiCustomer::getCustomerAddress, bo.getCustomerAddress());
        lqw.eq(bo.getCustomeLat() != null, LogiCustomer::getCustomeLat, bo.getCustomeLat());
        lqw.eq(bo.getCustomeLng() != null, LogiCustomer::getCustomeLng, bo.getCustomeLng());
        lqw.eq(bo.getCustomeWhseCapacity() != null, LogiCustomer::getCustomeWhseCapacity, bo.getCustomeWhseCapacity());
        lqw.eq(bo.getVehicleNum() != null, LogiCustomer::getVehicleNum, bo.getVehicleNum());
        lqw.eq(bo.getStaffNum() != null, LogiCustomer::getStaffNum, bo.getStaffNum());
        lqw.eq(StrUtil.isNotBlank(bo.getOtherInfo()), LogiCustomer::getOtherInfo, bo.getOtherInfo());
        lqw.eq(bo.getQuliFlag() != null, LogiCustomer::getQuliFlag, bo.getQuliFlag());
        lqw.eq(bo.getQuliTime() != null, LogiCustomer::getQuliTime, bo.getQuliTime());
        lqw.eq(StrUtil.isNotBlank(bo.getStatus()), LogiCustomer::getStatus, bo.getStatus());
        lqw.in(CollUtil.isNotEmpty(bo.getCustomerIdList()), LogiCustomer::getCustomerId, bo.getCustomerIdList());
        // 部门数据权限过滤
        if (ObjectUtil.isNotNull(bo.getDeptId())) {
            SqlUtil.dataPermissionFilter(lqw, bo.getDeptId());
        }
        return lqw;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByAddBo(LogiCustomerExtEditBo bo) {

        LogiCustomer customer = baseMapper.findByUk(bo.getMainDeptId(), bo.getCustomerCode());
        if (ObjectUtil.isNotEmpty(customer)) {
            throw new GlobalException("企业信用证代码已存在！");
        }
        LogiCustomer add = BeanUtil.toBean(bo, LogiCustomer.class);
        boolean ret = save(add);
        if (CollUtil.isEmpty(bo.getBookList())) {
            return ret;
        }

        bo.getBookList().forEach(Any-> Any.setCustomerId(add.getCustomerId()));
        return bookService.batchByAddBo(bo.getBookList());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByEditBo(LogiCustomerExtEditBo bo) {
        LogiCustomer update = BeanUtil.toBean(bo, LogiCustomer.class);

        if (StrUtil.isNotBlank(bo.getCustomerCode())) {
            LogiCustomer customer = baseMapper.findByUk(bo.getMainDeptId(), bo.getCustomerCode());
            if (ObjectUtil.isNotEmpty(customer) && !Objects.equals(customer.getCustomerId(), bo.getCustomerId())) {
                throw new GlobalException("企业信用证代码已存在！");
            }
        }

        boolean ret = updateById(update);
        bookService.remove(Wrappers.lambdaQuery(LogiCustomerBook.class).eq(LogiCustomerBook::getCustomerId, update.getCustomerId()));
        if (CollUtil.isEmpty(bo.getBookList())) {
            return ret;
        }
        bo.getBookList().forEach(Any-> Any.setCustomerId(update.getCustomerId()));
        return bookService.batchByAddBo(bo.getBookList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }
}
